package com.xlh.support.training.service.impl;

import com.google.common.collect.Lists;
import com.xlh.enums.SystemConfigEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.pojo.system.SystemConfig;
import com.xlh.security.UserInfoHolder;
import com.xlh.service.system.SystemConfigService;
import com.xlh.support.training.dao.TrainingMapper;
import com.xlh.support.training.dao.ext.TrainingMapperExt;
import com.xlh.support.training.dao.helper.TrainingMapperHelper;
import com.xlh.support.training.domain.Training;
import com.xlh.support.training.domain.TrainingAttr;
import com.xlh.support.training.po.TrainingSavePO;
import com.xlh.support.training.service.TrainingService;
import com.xlh.virtualization.constant.ContextTypeEnum;
import com.xlh.virtualization.service.ImageAllocationService;
import com.xlh.virtualization.service.ImageService;
import com.xlh.vo.IconVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.xlh.support.training.constant.TrainingConstant.SYSTEM_PRESET_CODE;
import static com.xlh.support.training.constant.TrainingConstant.TEACHER_MADE_CODE;

/**
 * @author cheer
 */
@Service
public class TrainingServiceImpl implements TrainingService {

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private ImageService imageService;

    @Autowired
    private ImageAllocationService imageAllocationService;

    @Autowired
    private TrainingMapper trainingMapper;

    @Autowired
    private TrainingMapperHelper trainingMapperHelper;

    @Autowired
    private TrainingMapperExt trainingMapperExt;

    @Override
    public List<IconVO> listTrainingIcons() {
        List<SystemConfig> systemConfigs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.TRAINING_ICON.getKey()));
        List<IconVO> iconVOS = new ArrayList<>();
        for (SystemConfig systemConfig : systemConfigs) {
            IconVO iconVO = IconVO.builder()
                    .icon(systemConfig.getId())
                    .iconUrl(SystemConfigEnum.TRAINING_ICON.getMappingUrl(systemConfig.getKeyValue()))
                    .build();
            iconVOS.add(iconVO);
        }
        return iconVOS;
    }

    @Override
    public List<TrainingAttr> listPublishedTrainings() {
        return trainingMapperExt.listPublishedTrainings();
    }

    @Override
    public List<TrainingAttr> listEditableTrainings(Long userId, Boolean isTeacher) {
        List<TrainingAttr> trainingAttrs;
        if (isTeacher) {
            trainingAttrs = trainingMapperExt.listTrainingsByUserId(userId);
        } else {
            trainingAttrs = trainingMapperExt.listPublishedTrainings();
        }
        return trainingAttrs;
    }

    @Override
    @Transactional
    public void updatePublishStatus(Long userId, Long trainingId, Boolean published) {
        Training training = trainingMapperHelper.getById(trainingId);
        if (training == null) {
            throw new GlobalException("环境实训不存在");
        }
        if (!Objects.equals(training.getUserId(), userId)) {
            throw new GlobalException("不能修改其他教师创建的实训的发布状态");
        }

        Training updateTraining = Training.builder()
                .id(training.getId())
                .published(published)
                .build();
        trainingMapper.updateByPrimaryKeySelective(updateTraining);

        imageService.updateSharedStatusByContext(ContextTypeEnum.TRAINING.getCode(), trainingId, published);
    }

    @Override
    public void createTraining(TrainingSavePO trainingSavePO) {
        String trainingName = StringUtils.trimToNull(trainingSavePO.getTrainingName());
        if (trainingMapperHelper.isExistsTrainingName(trainingName)) {
            throw new GlobalException("环境实训名称重复");
        }

        Training training = Training.builder()
                .trainingName(trainingName)
                .icon(trainingSavePO.getIcon())
                .trainingSource(userInfoHolder.isAdmin() ? SYSTEM_PRESET_CODE : TEACHER_MADE_CODE)
                .published(userInfoHolder.isAdmin())
                .description(trainingSavePO.getDescription())
                .userId(userInfoHolder.getUserId())
                .build();
        trainingMapper.insertSelective(training);
    }

    @Override
    @Transactional
    public void deleteTraining(Long trainingId) {
        Training training = trainingMapperHelper.getById(trainingId);
        if (training == null) {
            throw new GlobalException("环境实训不存在");
        }

        // 删除镜像分配
        imageAllocationService.deleteImageAllocation(ContextTypeEnum.TRAINING.getCode(), trainingId);
        // 删除镜像
        if (!training.getPublished()) {
            imageService.deleteImageByContext(ContextTypeEnum.TRAINING.getCode(), trainingId);
        }
        // 删除实训
        trainingMapper.deleteByPrimaryKey(trainingId);
    }

    @Override
    public void updateTraining(Long trainingId, TrainingSavePO trainingSavePO) {
        Training training = trainingMapperHelper.getById(trainingId);
        if (training == null) {
            throw new GlobalException("环境实训不存在");
        }

        String trainingName = StringUtils.trimToNull(trainingSavePO.getTrainingName());
        if (!StringUtils.equals(training.getTrainingName(), trainingName) &&
                trainingMapperHelper.isExistsTrainingName(trainingName)) {
            throw new GlobalException("环境实训名称重复");
        }

        Training updateTraining = Training.builder()
                .id(training.getId())
                .trainingName(trainingName)
                .icon(trainingSavePO.getIcon())
                .description(trainingSavePO.getDescription())
                .build();
        trainingMapper.updateByPrimaryKeySelective(updateTraining);
    }

    @Override
    public Training getTraining(Long trainingId) {
        return trainingMapperHelper.getById(trainingId);
    }
}
